<template>
  <div class="three-pie-wrap">
    <div class="three-pie" ref="pieDom">
      
      
    </div>
    <div class="three-pie-slot">
      <slot v-bind:data="currentData"></slot>
    </div>
    <div class="lengedList">
      <ul>
        <li :class="activeIndex===1?'activeLi':'detaultLi'">实业</li>
        <li :class="activeIndex===0?'activeLi':'detaultLi'">小贷</li>
        <li :class="activeIndex===4?'activeLi':'detaultLi'">保理</li>
        <li :class="activeIndex===3?'activeLi':'detaultLi'">供应链</li>
        <li :class="activeIndex===2?'activeLi':'detaultLi'">基金</li>
      </ul>
    </div>
  </div>
</template>

<script>
import * as THREE from "three"
import gsap from "gsap"
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"
import { emptyObject } from "@/mini3d"
import { deepClone } from "@/mini3d/utils/utils"
import ring2 from "@/assets/texture/pie/ring2.png"
import ring3 from "@/assets/texture/pie/ring3.png"
import ring4 from "@/assets/texture/pie/ring4.png"
export default {
  name: "ThreePie",
  props: {
    data: {
      type: Array,
      default: () => [],
    },
    colors: {
      type: Array,
      default: () =>  ["#5377F6", "#90CAFF", "#69EDF8", "#A3A7F4", "#63DBA4"],
    },
    opacity: {
      type: Number,
      default: 0.5,
    },
    delay: {
      type: Number,
      default: 5000,
    },
    loopComplete: {
      type: Function,
      default: () => {},
    },
  },
  computed: {
    currentData() {
      console.log(this.activeIndex)
      this.$emit("updatePie",this.data[this.activeIndex])
      return {
        ...this.data[this.activeIndex],
        count: this.count,
      }
    },
  },
  data() {
    this.circleMap = []
    this.scene = null
    this.camera = null
    this.renderer = null
    this.controls = null
    this.axes = null
    this.pointerGroup = []
    this.pieGroup = new THREE.Group()
    return {
      width: 300,
      height: 200,
      activeIndex: 0,
      count: 0,
      timer: null,
    }
  },
  created(){
    let circleData = deepClone(this.data)
    // 定义优先级顺序
    const order = ['保理', '小贷', '实业', '基金', '供应链'];
    // 按自定义顺序排序
    circleData.sort((a, b) => {
      return order.indexOf(a.name) - order.indexOf(b.name);
    });
    let total = 0;
    let c = []
    circleData.forEach((item,index)=>{
      total += item.value
      c.push(item.value)
    })
    c=c.map((iv,ik)=>{
      iv = iv/total
      return iv
    })
    const f = [10, 15, 10, 10, 10];        // 偏移量
    this.circleMap = this.calculateOffsetPoints(c,f,45)
    console.log(this.circleMap)
  },

  mounted() {
    this.width = this.$refs["pieDom"].offsetWidth
    this.height = this.$refs["pieDom"].offsetHeight
    this.count = this.data.map((item) => item.value).reduce((prev, current) => prev + current, 0)
    this.init()
    

  },
  beforeUnmount() {
    clearInterval(this.timer)
    this.destroy()
  },
  methods: {

    // Add this method to your component
    createSegmentIndicators() {
      // Define line colors (using your provided colors)
      const lineColors = ["#5377F6", "#90CAFF", "#69EDF8", "#A3A7F4", "#63DBA4"];
      // Define the line points based on your circleMap calculations
      const linePoints = this.circleMap.map(point => {
        // Start point is the edge of the pie segment
        const startX = point.x;
        const startY = point.y;
        
        // End point extends outward (adjust these multipliers as needed)
        const endX = point.x * 1.8;
        const endY = point.y * 1.8;
        // Middle point for the bend (you can adjust this)
        const midX = point.x * 1.4;
        const midY = point.y * 1.4;
        
        return [
          new THREE.Vector3(startX, startY, 0.1),
          new THREE.Vector3(midX, midY, 0.1),
          new THREE.Vector3(endX, endY, 0.1)
        ];
      });
      // Create lines for each segment
      linePoints.forEach((points, index) => {
        const lineGeometry = new THREE.BufferGeometry().setFromPoints(points);
        const lineMaterial = new THREE.LineBasicMaterial({
          color: new THREE.Color(lineColors[index]),
          linewidth: 2
        });
        const line = new THREE.Line(lineGeometry, lineMaterial);
        line.rotation.x = -Math.PI / 2; // Match pie rotation
        this.scene.add(line);
      });
      console.log("线条绘制结束")
    },
    init() {
      this.scene = new THREE.Scene()
      this.initCamera()
      this.initRenderer()
      this.initLight()
      this.initAxes()
      this.initControls()
      this.createPlane({
        url: ring2,
        width: 5,
        position: new THREE.Vector3(0, 0, -0.01),
        color: "#00ffff",
      })
      this.createPlane({
        url: ring3,
        width: 6.5,
        position: new THREE.Vector3(0, 0, -0.02),
        color: "#00ffff",
      })
      this.createPlane({
        url: ring4,
        width: 5.5,
        position: new THREE.Vector3(0, 0, -0.03),
        animate: true,
        color: "#00ffff",
      })
      this.createPie()
      this.loop()
    },
    //计算偏移 固定尺寸坐标
    calculateOffsetPoints(c, f, r) {
        // 验证输入
        if (c.length !== f.length || c.length !== 5) {
            throw new Error('c和f数组长度必须为5');
        }
        
        console.log(c)
        const total = c.reduce((sum, val) => sum + val, 0);
        if (Math.abs(total - 1.0) > 1e-6) {
            throw new Error('扇区占比总和必须等于1');
        }
        
        const points = [];
        let startAngle = -Math.PI / 2; // 从原点下方开始（即-90度）
        
        for (let i = 0; i < 5; i++) {
            // 计算当前扇区的角度范围
            const angle = c[i] * 2 * Math.PI;
            const midAngle = startAngle + angle / 2;
            
            // 计算外圆弧中间点坐标（未偏移）
            const originalX = r * Math.cos(midAngle);
            const originalY = r * Math.sin(midAngle);
            
            // 计算偏移后的点
            const offsetX = (r + f[i]) * Math.cos(midAngle);
            const offsetY = (r + f[i]) * Math.sin(midAngle);
            
            points.push({x:offsetX,y:offsetY});
            
            // 更新下一个扇区的起始角度
            startAngle += angle;
        }
        
        return points;
    },
    
    createPlane(opt) {
      let defaultOpt = {
        url: "texture/ring1.png",
        width: 5.5,
        z: 0,
        position: new THREE.Vector3(0, 0, 0),
        animate: false,
        color: null,
      }
      let options = Object.assign(defaultOpt, opt)
      const geometry = new THREE.PlaneGeometry(options.width, options.width)
      const material = new THREE.MeshBasicMaterial({
        map: this.getTexture(options.url),
        // color: 0x00ffff,
        transparent: true,
        side: THREE.DoubleSide,
        // depthWrite: false,
        depthTest: false,
      })
      if (options.color) {
        material.color = new THREE.Color(options.color)
      }
      const mesh = new THREE.Mesh(geometry, material)
      mesh.position.copy(options.position)
      mesh.rotation.x = (-1 * Math.PI) / 2
      if (options.animate) {
        gsap.to(mesh.rotation, {
          z: 2 * Math.PI,
          repeat: -1,
          ease: "none",
          duration: 3,
        })
      }
      this.scene.add(mesh)
    },
    getTexture(url) {
      const texture = new THREE.TextureLoader().load(url)
      texture.wrapS = texture.wrapT = THREE.RepeatWrapping
      return texture
    },
    createPie() {
      console.log(this.colors)
      let startAngle = 0
      let endAngle = 0
      this.pointerGroup = []

      for (var i = 0; i < this.data.length; i++) {
        let percent = this.data[i].value / this.count
        if (i == 0) {
          startAngle = 0
        } else {
          startAngle = endAngle + 0.0001
        }
        endAngle = endAngle + 2 * Math.PI * percent - 0.0001

        let ring = this.addRing({
          startAngle: startAngle,
          endAngle: endAngle,
          color: new THREE.Color(this.colors[i % this.colors.length]),
        })
        this.pointerGroup.push({
          name:this.data[i].name,
          value:this.data[i].value,
          percent:percent,
        })
        ring.name = "ring" + i
        this.pieGroup.add(ring)
      }
      
      this.scene.add(this.pieGroup)

      this.createSegmentIndicators(); // Add this line
      this.chooseRing(this.activeIndex, true)

      this.timer = setInterval(() => {
        this.loopChange()
      }, this.delay)
    },

    loopChange() {
      let index = this.activeIndex + 1

      if (index >= this.data.length) {
        index = 0
        this.loopComplete && this.loopComplete()
      }
      this.chooseRing(index)
    },
    chooseRing(activeIndex = 0, isFirst = false) {
      let prevIndex = activeIndex - 1 < 0 ? this.data.length - 1 : activeIndex - 1
      let prevMesh = this.pieGroup.children[prevIndex]
      this.prevMesh = prevMesh
      this.activeIndex = activeIndex
      let chooseMesh = this.pieGroup.children[activeIndex]
      if (!isFirst) {
        gsap.to(prevMesh.scale, { z: 1 })
        gsap.to(prevMesh.material, { opacity: this.opacity })
      }
      gsap.to(chooseMesh.scale, { z: 2 })
      gsap.to(chooseMesh.material, { opacity: 0.8 })
    },
    addRing(opt = {}) {
      let defaultOpt = {
        innerRadius: 1.5, // 内圆半径
        outerRadius: 2, // 外援半径
        thickness: 0.5, // 厚度
        startAngle: 0,
        endAngle: Math.PI / 2,
        color: 0x00ffff,
        segments: 120,
      }
      let options = Object.assign(defaultOpt, opt)
      // 外层
      let outerShape = new THREE.Shape()
      outerShape.arc(0, 0, options.outerRadius, options.startAngle, options.endAngle)
      let outerPoints = outerShape.getPoints(options.segments)
      // 内层：需要把开始结束角度调换下，并反向绘制
      let innerShape = new THREE.Shape()
      innerShape.arc(0, 0, options.innerRadius, options.endAngle, options.startAngle, true)
      let innerPoints = innerShape.getPoints(options.segments)
      // 组合内外侧的点，并重新生成shape
      let shape = new THREE.Shape(outerPoints.concat(innerPoints))
      // 扩展设置
      const extrudeSettings = {
        steps: 1,
        depth: options.thickness,
        bevelEnabled: true,
        bevelThickness: 0,
        bevelSize: 0,
        bevelOffset: 0,
        bevelSegments: 0,
      }
      const extruGeometry = new THREE.ExtrudeGeometry(shape, extrudeSettings)
      let material = new THREE.MeshLambertMaterial({
        color: options.color,
        transparent: true,
        opacity: this.opacity,
        side: THREE.DoubleSide,
      })
      const mesh = new THREE.Mesh(extruGeometry, material.clone())
      mesh.renderOrder = 10
      mesh.rotation.x = (-1 * Math.PI) / 2
      return mesh
    },
    initCamera() {
      var rate = this.width / this.height
      this.camera = new THREE.PerspectiveCamera(30, rate, 0.1, 1500)
      // this.camera .position.set(4.972679988078243, 4.643664044427053, 5.723022308725478)
      this.camera.position.set(6.023813305272227, 4.838542633695233, 4.111272698256137)
      this.camera.lookAt(0, 0, 0)
    },

    initRenderer() {
      this.renderer = new THREE.WebGLRenderer({
        antialias: true,
        alpha: true,
      })
      this.renderer.setPixelRatio(window.devicePixelRatio)
      this.renderer.setSize(this.width, this.height)
      this.$refs["pieDom"].appendChild(this.renderer.domElement)
    },

    initLight() {
      //   平行光1
      let directionalLight1 = new THREE.DirectionalLight(0xffffff, 2)
      directionalLight1.position.set(200, 300, 200)
      //   平行光2
      let directionalLight2 = new THREE.DirectionalLight(0xffffff, 2)
      directionalLight2.position.set(-200, -300, -200)
      // 环境光
      let ambientLight = new THREE.AmbientLight(0xffffff, 2)
      // 将光源添加到场景中
      this.scene.add(directionalLight1)
      this.scene.add(directionalLight2)
      this.scene.add(ambientLight)
    },

    initAxes() {
      this.axes = new THREE.AxesHelper(0)
      this.scene.add(this.axes)
    },

    initControls() {
      this.controls = new OrbitControls(this.camera, this.renderer.domElement)
      this.controls.maxPolarAngle = Math.PI
      this.controls.autoRotate = false
      this.controls.enableDamping = true
      this.controls.enabled = false
    },

    loop() {
      this.renderer.setAnimationLoop(() => {
        this.renderer.render(this.scene, this.camera)
        this.controls && this.controls.update()
        // console.log(this.camera .position);
      })
    },
    start() {
      this.loop()
      this.controls.enabled = true
      this.timer = setInterval(() => {
        this.loopChange()
      }, this.delay)
    },
    stop() {
      clearInterval(this.timer)
      if (this.controls) {
        this.controls.enabled = false
      }
      if (this.renderer) {
        this.renderer.setAnimationLoop(null)
      }
    },
    // 获取场景
    getScene() {
      return this.scene
    },
    getRender() {
      return this.renderer
    },
    resize() {
      this.width = this.$refs["pieDom"].offsetWidth
      this.height = this.$refs["pieDom"].offsetHeight
      let aspect = this.width / this.height
      this.camera.aspect = aspect
      this.camera.updateProjectionMatrix()
      this.renderer.setSize(this.width, this.height)
      this.renderer.setPixelRatio(window.devicePixelRatio)
    },
    destroy() {
      if (this.prevMesh) {
        gsap.set(this.prevMesh.scale, { z: 1 })
        gsap.set(this.prevMesh.material, { opacity: this.opacity })
      }
      this.stop()
      window.removeEventListener("resize", () => {
        this.resize()
      })
      if (this.renderer) {
        emptyObject(this.pieGroup)
        this.renderer.dispose()
        this.renderer.forceContextLoss()
        this.controls.dispose()
        this.$refs["pieDom"].innerHTML = ""
        this.scene = null
        this.camera = null
        this.renderer = null
        this.controls = null
        this.axes = null
      }
    },
  },
}
</script>

<style scoped lang="scss">
.three-pie-wrap {
  position: relative;
  width: 100%;
  height: 100%;
  z-index: 2;
}
.three-pie {
  width: 100%;
  height: 100%;
  position: relative;
  margin-left: -80px;
  
}
.three-pie-slot {
  position: absolute;
  left:-80px;
  top: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
.lengedList{
  position: absolute;
  right: 44px;
  top: 50%;
  margin-top: 20px;
  transform: translateY(-50%);
  ul{
    li{
      list-style: none;
      font-weight: 400;
      font-size: 12px;
      color: #FFFFFF;
      line-height: 17px;
      margin-bottom: 20px;
    }
    li::before{
      display: inline-block;
      content: "";
      width: 12px;
      height: 12px;
      background: #79B7FF;
      border-radius: 50%;
      margin-right: 8px;
      vertical-align: middle;
    }
    li:nth-of-type(2)::before{
      background: #2E55E0;
    }
    li:nth-of-type(3)::before{
      background: #64DE9C;
    }
    li:nth-of-type(4)::before{
      background: #9290F3;
    }
    li:nth-of-type(5)::before{
      background: #05C2D1;
    }
    .activeLi{
      font-weight: 600;
      font-size: 12px;
      color: #FFFFFF;
      line-height: 17px;
      text-shadow: 0px 0px 6px rgba(0,246,255,0.57);
    }
  }
}
.baoxian{
  position:absolute;
  left: 50%;
  top: 50%;
  width: 128px;
  height: 44px;
  background: url(../../assets/images/baoxianIcon2.png);
  background-size: 100% 100%;
  text-align: center;
  font-size: 12px;
  font-weight: 400;
  line-height:44px;
  text-indent:44px;
  color:#ffffff;
  transform:translate(-50%,-50%);
}
.gongyinglian{
  position:absolute;
  left: 50%;
  top: 50%;
  width: 127px;
  height: 49px;
  background: url(../../assets/images/gongyinglian_icon2.png);
  background-size: 100% 100%;
  text-align: center;
  font-size: 12px;
  font-weight: 400;
  line-height:50px;
  text-indent:-40px;
  color:#ffffff;
  transform:translate(-50%,-50%);
}
.xiaodai{
  position:absolute;
  left: 50%;
  top: 50%;
  width: 127px;
  height: 49px;
  background: url(../../assets/images/xiaodai_icon2.png);
  background-size: 100% 100%;
  text-align: center;
  font-size: 12px;
  font-weight: 400;
  line-height:46px;
  text-indent:34px;
  color:#ffffff;
  transform:translate(-50%,-50%);
}
.shiye{
  position:absolute;
  left: 50%;
  top: 50%;
  width: 140px;
  height: 57px;
  background: url(../../assets/images/shiye_icon2.png);
  background-size: 100% 100%;
  text-align: center;
  font-size: 12px;
  font-weight: 400;
  line-height:40px;
  text-indent:-62px;
  color:#ffffff;
  transform:translate(-50%,-50%);
}
.jijin{
  position:absolute;
  left: 50%;
  top: 50%;
  width: 117.45px;
  height: 32.79px;
  background: url(../../assets/images/jinji_icon2.png);
  background-size: 100% 100%;
  text-align: center;
  font-size: 12px;
  font-weight: 400;
  line-height:34px;
  text-indent:-40px;
  color:#ffffff;
  transform:translate(-50%,-50%);
}
.circle_center{
  position: absolute;
  width: 20px;
  height: 20px;
  left: 50%;
  top: 50%;
  transform: translate(-50%,-50%);
  display: none;
}
</style>
